package edu.hawaii.halealohacli;

import java.util.AbstractList;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.TreeSet;

/**
 * Tree -storage class.
 * 
 * @author John MacMillan
 * @author Mitchell Kupfer
 * @author Bryson Hori
 * @author Chris Fang
 * @author Chris Wilson
 * @author Daniel Ly
 * @author Jordan Do
 */
public class Tree {

  /**
   * A static collection of available commands.
   */
  protected AbstractSet<Node> tree;

  /**
   * Default constructor, no parameters, creates the static tree.
   */
  public Tree() {
    tree = new TreeSet<Node>();
  }

  /**
   * Builds the tree with static variables.
   */
  public void buildTree() {
    putInfo("current-power");
    putInfo("quit");
    putInfo("daily-energy");
    putInfo("energy-since");
    putInfo("rank-towers");
    putInfo("set-baseline");
    putInfo("monitor-power");
    putInfo("monitor-goal");
    putInfo("help");
  }

  /**
   * Adds a node with the passed in name.
   * 
   * @param name name of the node.
   */
  public void putInfo(String name) {
    Node nody = new Node(name);
    tree.add(nody);
  }

  /**
   * Checks if the argument has a corresponding class.
   * 
   * @param name the name of the argument.
   * @return true if the command has a corresponding class.
   */
  public boolean contains(String name) {

    // create iterator for the tree
    Iterator<Node> iter = tree.iterator();

    // if the name is in the tree return true
    while (iter.hasNext()) {
      if (iter.next().name.equals(name)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Creates and returns an instance if the command class.
   * 
   * @param command the users command they want executed.
   * @param strings the arguments the user input.
   * @return a boolean, true if number of arguments is correct.
   */
  public boolean checkInput(String command, AbstractList<String> strings) {

    // debugging lines ======================================
    /*
     * System.out.println("\n\nCommand: " + command); System.out.println("number of args: " +
     * (strings.size() - 1)); for (String s : strings) { System.out.println("parsed words: " + s); }
     */
    // end debugging lines =================================

    // based on the command checks the number of arguments given.
    try {

      if (command.equalsIgnoreCase("current-power")) {
        if (strings.size() - 1 == 1) {
          return true;
        }
      }
      else if (command.equalsIgnoreCase("help")) {

        if (strings.size() - 1 == 0) {
          return true;
        }
      }
      else if (command.equalsIgnoreCase("daily-energy")) {
        if (strings.size() - 1 == 2) {
          return true;
        }

      }
      else if (command.equalsIgnoreCase("energy-since")) {
        if (strings.size() - 1 == 2) {
          return true;
        }

      }
      else if (command.equalsIgnoreCase("rank-towers")) {
        if (strings.size() - 1 == 2) {
          return true;
        }

      }
      else if (command.equalsIgnoreCase("set-baseline")) {
        if (strings.size() - 1 == 1 || strings.size() - 1 == 2) {
          return true;
        }
        
      }
      else if (command.equalsIgnoreCase("monitor-power")) {
        if (strings.size() - 1 == 1 || strings.size() - 1 == 2) {
          return true;
        }

      }
      else if (command.equalsIgnoreCase("monitor-goal")) {
        if (strings.size() - 1 == 3) {
          return true;
        }

      }

      else {
        return false;
      }

    }

    catch (Exception e) {
      return false;
    }

    return false;
  }

}

/**
 * Node class used within Storage class, holds a name. implements comparable.
 * 
 * @author John MacMillan
 * @author Mitchell Kupfer
 * @author Bryson Hori
 * 
 */
class Node implements Comparable<Node> {
  protected String name;

  /**
   * Default constructor takes a name and a number.
   * 
   * @param name the name of a given object.
   */
  public Node(String name) {
    this.name = name;
  }

  /**
   * An override for the compareTo method using the number field.
   * 
   * @return int used for default compareTo.
   * @param node the node that is being compared to.
   */
  @Override
  public int compareTo(Node node) {

    if (node.name.compareTo(this.name) > 0) {
      return 1;
    }

    else {
      return -1;
    }
  }

  /**
   * Override for equals method.
   * 
   * @return a boolean for equality.
   * @param node the node to be compared to.
   */
  @Override
  public boolean equals(Object node) {
    if (node instanceof Node) {

      Node nody = (Node) node;
      if (this.name.equals(nody.name)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Override method for the hashcode.
   * 
   * @return the int hash code.
   */
  @Override
  public int hashCode() {
    return this.name.length() % 10;
  }
}
